package com.amado.course42Nio.charSystem;

import com.amado.course42Nio.demo2.Buffers;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
 * @author wangyulong
 * @version 1.5.0
 * @date 2020/3/8 20:41
 */
public class CharServer {
    Selector selector;
    Set<String> nameSet = new HashSet<>();

    public static void main(String[] args) throws IOException {
        new CharServer().go();
    }

    public CharServer() throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        ServerSocket socket = serverSocketChannel.socket();
        socket.bind(new InetSocketAddress( 4444));
        selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("启动成功");
    }

    public void go() throws IOException {
        while (true) {
            int selectCount = selector.select();
            if(selectCount==0){
                continue;
            }
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                if (selectionKey.isAcceptable()) {
                    accept(selectionKey);
                } else if (selectionKey.isReadable()) {
                    read(selectionKey);
                }
            }
        }
    }

    private void accept(SelectionKey selectionKey) throws IOException {
        ServerSocketChannel channel = (ServerSocketChannel)selectionKey.channel();
        SocketChannel socketChannel = channel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.put((CommandEnum.SET_NAME.getCommand()+"##null##欢迎进入聊天室,在线人数，请输入姓名").getBytes());
        byteBuffer.flip();
        //将此对应的channel设置为准备接受其他客户端请求
        socketChannel.write(byteBuffer);
        System.out.println("总连接 "+selector.selectedKeys().size());
        System.out.println("连接进来");
        System.out.println("回写数据");
    }

    private void read(SelectionKey selectionKey) throws IOException {
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        channel.read(readBuffer);
        readBuffer.flip();
        CharBuffer charBuffer = Charset.forName("UTF-8").decode(readBuffer);
        String content = new String(charBuffer.array());
        System.out.println("收到" + content);
        //输入姓名
        String name = getName(content);
        String realConent = getContent(content);
        if("1".equals(getCommand(content))){
            if(nameSet.contains(name)){
                repeatName(channel);
            }else{
                nameSet.add(name);
                nameIsOk(channel,name);
            }
        }else {
            //广播消息
            broadcast(channel, name, realConent);
        }
    }

    private void nameIsOk(SocketChannel socketChannel,String name) throws IOException {
        ByteBuffer wrap = ByteBuffer.wrap((CommandEnum.NAME_OK.getCommand()+"##"+name+"##").getBytes());
        socketChannel.write(wrap);
    }
    private void repeatName(SocketChannel socketChannel) throws IOException {
        ByteBuffer wrap = ByteBuffer.wrap((CommandEnum.NAME_EXISTS.getCommand()+"##null##name is repeat").getBytes());
        socketChannel.write(wrap);
    }
    /**
     * 广播消息
     * @throws IOException
     */
    private void broadcast(SocketChannel excpet,String name,String contet) throws IOException {
        for (SelectionKey key : selector.keys()) {
            SelectableChannel channel = key.channel();
            if(channel instanceof SocketChannel && channel!=excpet){
                SocketChannel socketChannel = (SocketChannel) channel;
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                byteBuffer.put((CommandEnum.CHARS.getCommand()+"##"+name+"##"+contet).getBytes());
                byteBuffer.flip();
                socketChannel.write(byteBuffer);
            }
        }

    }
    private String getCommand(String content){
        String contentArray[]  = content.split("##");
        return contentArray[0];
    }
    private String getName(String content){
        String contentArray[]  = content.split("##");
        return contentArray[1];
    }
    private String getContent(String content){
        String contentArray[]  = content.split("##");
        return contentArray[2];
    }
}
